﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Moon.Sql
{
    /// <summary>
    /// 实体类映射
    /// </summary>
    internal class ClassMapper
    {
        /// <summary>
        /// 实体类映射
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static MapperTable Mapping<T>()
        {
            MapperTable mapperTable = new MapperTable()
            {
                EntityType = typeof(T),
                Properties = new List<PropertyMap>(),
                PropertiesDict = new Dictionary<string, PropertyMap>()
            };
            SetTableName(mapperTable);
            SetProperties(mapperTable);
            return mapperTable;
        }

        /// <summary>
        /// 实体类映射
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static MapperTable Mapping(Type type)
        {
            MapperTable mapperTable = new MapperTable()
            {
                EntityType = type,
                Properties = new List<PropertyMap>(),
                PropertiesDict = new Dictionary<string, PropertyMap>()
            };
            SetTableName(mapperTable);
            SetProperties(mapperTable);
            return mapperTable;
        }

        /// <summary>
        /// 实体类映射
        /// </summary>
        /// <param name="typeArguments"></param>
        /// <returns></returns>
        public static List<MapperTable> Mapping(params Type[] typeArguments)
        {
            if (typeArguments == null || typeArguments.Length == 0) throw new Exception("the parameter is empty");
            List<MapperTable> list = new List<MapperTable>();
            foreach (var item in typeArguments)
            {
                list.Add(Mapping(item));
            }
            return list;
        }

        /// <summary>
        /// 获取表名
        /// </summary>
        /// <param name="mapperTable"></param>
        private static void SetTableName(MapperTable mapperTable)
        {
            mapperTable.TableName = mapperTable.EntityType.Name;
            var tableAttribute = mapperTable.EntityType.GetCustomAttributes(typeof(MoonTableAttribute), true).FirstOrDefault();
            if (tableAttribute != null)
            {
                mapperTable.TableName = ((MoonTableAttribute)tableAttribute).Name;
            }
        }

        /// <summary>
        /// 获取实体类中所有属性
        /// </summary>
        /// <param name="mapperTable"></param>
        private static void SetProperties(MapperTable mapperTable)
        {
            foreach (var propertyInfo in mapperTable.EntityType.GetProperties())
            {
                PropertyMap propertyMap = new PropertyMap()
                {
                    ColumnName = propertyInfo.Name,
                    PropertyInfo = propertyInfo,
                    IsIdentity = false,
                    Name = propertyInfo.Name,
                    IsPrimaryKey = false
                };

                var dga = propertyInfo.GetCustomAttributes(typeof(MoonIdentityAttribute), true).FirstOrDefault();
                if (dga != null)
                {
                    //自增长
                    propertyMap.IsIdentity = true;

                    var seq = propertyInfo.GetCustomAttributes(typeof(MoonSequenceAttribute), true).FirstOrDefault();
                    if (seq != null)
                    {
                        propertyMap.SequenceName = (seq as MoonSequenceAttribute)?.Name;
                    }
                }

                var columnAttribute = propertyInfo.GetCustomAttributes(typeof(MoonColumnAttribute), true).FirstOrDefault();
                if (columnAttribute != null)
                {
                    //数据库表中列名
                    propertyMap.ColumnName = ((MoonColumnAttribute)columnAttribute).Name;
                    propertyMap.ColumnSize = ((MoonColumnAttribute)columnAttribute).Size;
                }

                var keyAttribute = propertyInfo.GetCustomAttributes(typeof(MoonKeyAttribute), true).FirstOrDefault();
                if (keyAttribute != null)
                {
                    //主键
                    propertyMap.IsPrimaryKey = true;
                }

                var ignoredAttribute = propertyInfo.GetCustomAttributes(typeof(MoonIgnoredAttribute), true).FirstOrDefault();
                if (ignoredAttribute != null)
                {
                    //忽略
                    propertyMap.Ignored = true;
                }

                mapperTable.Properties.Add(propertyMap);
                mapperTable.PropertiesDict.Add(propertyMap.Name, propertyMap);
            }
        }
    }
}
